import 'dart:convert';
import 'dart:io';

import 'package:device_info_plus/device_info_plus.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:squat_easy/se_constant.dart';
import 'package:squat_easy/se_net/se_global_url.dart';
import 'package:squat_easy/se_net/se_net.dart';
import 'package:squat_easy/se_ui/se_dialogs.dart';
import 'package:ylm_ui_kit/ylm_ui_kit.dart';

class SeDeviceInfoUtils {
  SeDeviceInfoUtils._internal();

  factory SeDeviceInfoUtils() => _instance;

  static final SeDeviceInfoUtils _instance = SeDeviceInfoUtils._internal();

  final DeviceInfoPlugin _deviceInfo = DeviceInfoPlugin();

  String deviceId = '';
  String deviceModel = '';
  String deviceLanguageCode = '';

  Future init() async {
    if (Platform.isAndroid) {
      AndroidDeviceInfo androidInfo = await _deviceInfo.androidInfo;
      deviceId = androidInfo.id;
      deviceModel = androidInfo.model;
    } else if (Platform.isIOS) {
      IosDeviceInfo iosInfo = await _deviceInfo.iosInfo;
      deviceId = iosInfo.identifierForVendor ?? '';
      deviceModel = iosInfo.utsname.machine;
    }

    List<String> languageCode = Platform.localeName.split('_');
    if (languageCode.isNotEmpty) {
      deviceLanguageCode = languageCode.first;
    } else {
      deviceLanguageCode = Platform.localeName;
    }
  }
}

class SePackageInfoUtils {
  SePackageInfoUtils._internal();

  factory SePackageInfoUtils() => _instance;

  static final SePackageInfoUtils _instance = SePackageInfoUtils._internal();

  String packageName = '';
  String version = '';
  String build = '';

  Future init() async {
    final PackageInfo packageInfo = await PackageInfo.fromPlatform();
    packageName = packageInfo.packageName;
    version = packageInfo.version;
    build = packageInfo.buildNumber;
  }
}

///提供netBuilder
abstract class SeCoreNetBuilder extends SeNetBuilder {
  String? version;
  String? identity;

  @override
  Future<Map<String, dynamic>> initHeaders() async {
    Map<String, dynamic> headers = {};
    headers['device-id'] = SeDeviceInfoUtils().deviceId; // 设备id或者udid，保证当前设备唯一值
    if (Platform.isAndroid) {
      headers['platform'] = 'Android';
    } else if (Platform.isIOS) {
      headers["platform"] = "iOS";
    }
    headers['model'] = SeDeviceInfoUtils().deviceModel; // 设备型号
    headers['pkg'] = SePackageInfoUtils().packageName; // 包名
    headers['pkg'] = 'test.bigegg.ios'; // 包名
    headers['ver'] = SePackageInfoUtils().version; // 版本 例如1.0.0，读取实际配置的版本号
    headers['p_ver'] = SePackageInfoUtils().build; // build number
    headers['kst'] = '1'; // 固定传1
    headers['sys_lan'] = SeDeviceInfoUtils().deviceLanguageCode; // 手机系统语言 如英文en
    headers['lang'] = SeDeviceInfoUtils().deviceLanguageCode; // 手机系统语言 如英文en
    headers['Authorization'] = 'Bearer${CommonStorage().getString(SeStorageKey.spKeyToken, defaultValue: '')}';
    headers['content-type'] = 'application/json';
    return headers;
  }

  ///throw Exception(); 可以让下一步的[showError]不进行弹窗提示
  @override
  Future reduceJson(dynamic result) async {
    Map json;
    if (result is String) {
      json = jsonDecode(result);
    } else {
      json = result;
    }

    int code = json['code'];
    String msg = json['msg'] ?? "Request error，$code";

    ///请求成功
    if (code == 0) {
      if (json.containsKey("data")) {
        return json["data"];
      } else {
        return json;
      }
    }

    ///未提供token、token格式错误、无效token、token过期、其他设备登录
    if (code == 10010301 || code == 10010302 || code == 100103 || code == 10010303 || code == 10010304) {
      SeDialogs.showLoginDialog();
      return SeNetOtherError();
    }

    ///token为空
    if (code == 10010307) {
      return SeNetOtherError();
    }

    ///金币不足
    if (code == 20010009) {
      throw Exception(msg);
    }

    throw Exception(msg);
  }

  @override
  void showError(SeNetError errorType, Exception error) {
    switch (errorType) {
      case SeNetError.netError:
        // Loading.toast('Please check the network connection');
        return;
      case SeNetError.connectTimeout:
        // Loading.toast('Connection timeout');
        return;
      case SeNetError.sendTimeout:
        // Loading.toast('Send timeout');
        return;
      case SeNetError.receiveTimeout:
        // Loading.toast('Receive timeout');
        return;
      case SeNetError.formatError:
        // Loading.toast('Data format error');
        return;
      case SeNetError.cancel:
        // Loading.toast('Request cancel');
        return;
      case SeNetError.other:
      default:
        // if (error.toString() == 'Exception') return;
        // Loading.toast(
        //   error.toString().replaceAll("Exception: ", ""),
        // );
        return;
    }
  }

  @override
  void print(msg) {
    // Log.log('----- net error ----- :$msg');
  }
}

class SeProductNetBuilder extends SeCoreNetBuilder {
  @override
  String getBaseUrl() => SeGlobalUrl.apiBaseRelease;

  @override
  Future<Map<String, dynamic>> initAutoPostParams() async => Future.value({});
}

class SeDebugNetBuilder extends SeCoreNetBuilder {
  SeDebugNetBuilder(this.mode);

  final SeDebugMode mode;

  @override
  String getBaseUrl() => SeDebugMode.debug == mode ? SeGlobalUrl.apiBaseDebug : SeGlobalUrl.apiBaseRelease;

  @override
  Future<Map<String, dynamic>> initAutoPostParams() async => Future.value({});
}

enum SeDebugMode {
  debug,
  release,
}
